import socket
import threading
import time
import local_var


def create_socket():
    """
    创建服务端Socket
    :return: None
    """
    local_var.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    host = '127.0.0.1'
    port = 666
    local_var.server_socket.bind((host, port))
    local_var.server_socket.settimeout(25)
    print('timeout time:', local_var.server_socket.gettimeout())
    local_var.server_socket.listen(10)


# 这个函数在退出时运行一次，以防止 run_tcp_server 因 accept 阻塞而无法退出
def run_client():
    local_var.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    host = '127.0.0.1'
    print(host)
    port = 9999
    try:
        local_var.client_socket.connect((host, port))
        local_var.client_socket.close()
    except Exception as e:
        print('except at run client: ', e)


def run_tcp_server():
    create_socket()
    while local_var.server_on:
        try:
            client_socket, addr = local_var.server_socket.accept()
        except socket.timeout:
            print('socket time out!')
            continue
        local_var.connect_list[addr] = {'socket': client_socket, 'in_listen': True}
        t = threading.Thread(target=receive_threading, args=(addr,))
        try:
            t.start()
        except Exception as e:
            print('except on run_tcp_server 2: ', e)
            client_socket.close()
        print(f'Client address: {addr}')
        msg = 'Hello client! ' + '\r\n'
        try:
            client_socket.send(msg.encode('utf-8'))
        except Exception as e:
            print('except on run_tcp_server 2: ', e)
        # client_socket.close()


def receive_threading(the_addr):
    in_listen = local_var.connect_list[the_addr]['in_listen']
    the_socket = local_var.connect_list[the_addr]['socket']
    while in_listen:
        try:
            s = the_socket.recv(1000)
            print(s)
            if len(s) == 0:
                the_socket.close()
                local_var.connect_list.pop(the_addr)
                in_listen = False
            else:
                print(s)
        except Exception as e:
            print(f'except on receive_threading: address{the_addr}', e)
            the_socket.close()
            local_var.connect_list.pop(the_addr)
            in_listen = False


def control_timer():
    # 设置定时，模仿退出命令事件的输入
    time.sleep(20)
    print('time over!')
    # 改变循环变量，使得 run_tcp_server() 的循环退出
    local_var.server_on = False
    # 运行一下client端连接，保证 run_tcp_server() 的 accept 退出阻塞
    run_client()
    # 停止所有接收子线程（receive_threading），这时不怕 recv 函数阻塞，因为服务端将退出，从而使 recv 产生异常
    for i in local_var.connect_list.keys():
        local_var.connect_list[i]['in_listen'] = False
    # local_var.py.control_queue.put('stop')
    # print(local_var.py.control_queue.qsize())


if __name__ == '__main__':
    # 是否继续
    local_var.server_on = True
    t_outside = threading.Thread(target=run_tcp_server)
    t_outside.start()
    t_timer = threading.Thread(target=control_timer)
    t_timer.start()
    t_outside.join()
    t_timer.join()
